package com.huxi.lang.object;

import java.util.Locale;

/**
 * 键风格枚举类型
 * 
 * @since 1.0
 * @author jian.wu
 *
 */
public enum KStyle {

	/**
	 * 没有风格
	 */
	NONE(false, false, false, false),

	/**
	 * 全部小写风格，如： username
	 */
	LOWER(true, false, false, false),

	/**
	 * 全部大写风格，如： USERNAME
	 */
	UPPER(false, true, false, false),

	/**
	 * 驼峰风格，如： userName
	 */
	CAMEL_CASE(false, false, true, false),

	/**
	 * 下划线且全部小写风格，如：user_name
	 */
	SNAKE_CASE_LOWER(true, false, false, true),
	/**
	 * 下划线且全部大写风格，如：USER_NAME
	 */
	SNAKE_CASE_UPPER(false, true, false, true);

	private final boolean lower;
	private final boolean upper;
	private final boolean camel;
	private final boolean snake;

	private KStyle(boolean lower, boolean upper, boolean camel, boolean snake) {
		this.lower = lower;
		this.upper = upper;
		this.camel = camel;
		this.snake = snake;
	}

	/**
	 * 是否全部小写风格
	 * 
	 * @return 全部小写风格返回真，否则返回假。
	 */
	public boolean isLower() {
		return lower;
	}

	/**
	 * 是否全部大写风格
	 * 
	 * @return 全部大写风格返回真，否则返回假。
	 */
	public boolean isUpper() {
		return upper;
	}

	/**
	 * 是否驼峰名称风格
	 * 
	 * @return 驼峰名称风格返回真，否则返回假。
	 */
	public boolean isCamel() {
		return camel;
	}

	/**
	 * 是否下划线风格风格
	 * 
	 * @return 下划线风格风格返回真，否则返回假。
	 */
	public boolean isSnake() {
		return snake;
	}

	/**
	 * 文本首字母小写
	 * 
	 * @param key 文本
	 * @return 文本首字母大写则返回新文本，否则直接返回原文本。
	 */
	public static String firstLowerCase(String key) {
		if (!(key == null || key.length() == 0)) {
			char first = key.charAt(0);
			if (Character.isUpperCase(first)) {
				if (key.length() == 1) {
					return key.toLowerCase(Locale.ROOT);
				}
				StringBuilder sb = new StringBuilder(key.length());
				sb.append(Character.toLowerCase(first)).append(key, 1, key.length());
				return sb.toString();
			}
		}
		return key;
	}

	/**
	 * 文本首字母大写
	 * 
	 * @param key 文本
	 * @return 文本首字母小写则返回新文本，否则直接返回原文本。
	 */
	public static String firstUpperCase(String key) {
		if (!(key == null || key.length() == 0)) {
			char first = key.charAt(0);
			if (Character.isLowerCase(first)) {
				if (key.length() == 1) {
					return key.toUpperCase(Locale.ROOT);
				}
				StringBuilder sb = new StringBuilder(key.length());
				sb.append(Character.toUpperCase(first)).append(key, 1, key.length());
				return sb.toString();
			}
		}
		return key;
	}

	private static char toUpperCase(char c) {
		if (Character.isLowerCase(c)) {
			return Character.toUpperCase(c);
		}
		return c;
	}

	@SuppressWarnings("unused")
	private static char toLowerCase(char c) {
		if (Character.isUpperCase(c)) {
			return Character.toLowerCase(c);
		}
		return c;
	}

	/**
	 * 下划线风格转换为驼峰风格
	 * 
	 * @param key 下划线风格文本
	 * @return 驼峰风格文本，首字母小写。
	 */
	public static String camelFromSnake(String key) {
		if (!(key == null || key.length() == 0)) {
			StringBuilder sb = null;
			int first = 0;
			int next = -1;
			while ((next = key.indexOf('_', first)) != -1) {
				if (sb == null) {
					sb = new StringBuilder(key.length());
				}
				if (next != first) {
					if (first == 0) {
						sb.append(key, first, next);
					} else {
						sb.append(toUpperCase(key.charAt(first))).append(key, first + 1, next);
					}
				}
				first = next + 1;
			}
			if (sb != null) {
				if (first < key.length()) {
					sb.append(toUpperCase(key.charAt(first))).append(key, first + 1, key.length());
				}
				return sb.toString();
			}
		}
		return key;
	}

	/**
	 * 驼峰风格转换为下划线小写风格
	 * 
	 * @param key 驼峰风格文本
	 * @return 下划线小写风格
	 */
	public static String snakeFromCamel(String key) {
		if (!(key == null || key.length() == 0)) {
			StringBuilder sb = null;
			int first = 0;
			for (int i = 0; i < key.length(); i++) {
				char cp = key.charAt(i);
				if (Character.isUpperCase(cp)) {
					if (sb == null) {
						sb = new StringBuilder(key.length() + 8);
					}
					if (first != i) {
						sb.append(key, first, i);
					}
					sb.append('_').append(Character.toLowerCase(cp));
					first = i + 1;
				}
			}
			if (sb != null) {
				if (first < key.length()) {
					sb.append(key, first, key.length());
				}
				return sb.toString();
			}
		}
		return key;
	}

	/**
	 * 大小写风格标准化
	 * 
	 * @param key 原始文本
	 * @return 标准后文本
	 */
	public String standard(String key) {
		if (key == null || key.length() == 0) {
			return key;
		}

		if (isLower()) {
			return key.toLowerCase(Locale.ROOT);
		}

		if (isUpper()) {
			return key.toUpperCase(Locale.ROOT);
		}

		return key;
	}

	/**
	 * 文本风格转换
	 * 
	 * @param key   原始文本
	 * @param style 原始风格
	 * @return 风格文本
	 */
	public String standardFromStyle(String key, KStyle style) {
		if (key == null || style == this || NONE == this) {
			return key;
		}

		if (style == null) {
			return this.standard(key);
		}

		if (this.isCamel()) {
			if (style.isSnake()) {
				if (!style.isLower()) {
					key = key.toLowerCase(Locale.ROOT);
				}
				return camelFromSnake(key);
			}
			return key;
		}

		if (this.snake) {
			if (style.camel) {
				key = snakeFromCamel(key);
			}
			if (this.isUpper()) {
				return key.toUpperCase(Locale.ROOT);
			} else if (this.isLower()) {
				return key.toLowerCase(Locale.ROOT);
			} else {
				return key;
			}
		}

		if (this.isLower()) {
			return style.isLower() ? key : key.toLowerCase(Locale.ROOT);
		}

		if (this.isUpper()) {
			return style.isUpper() ? key : key.toUpperCase(Locale.ROOT);
		}

		return key;
	}

}
